package com.apes.fn.fico.reimbursement.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.Arith;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.*;

/**
 * @author cyy
 */
@Service("accrualBasisService")
public class AccrualBasisService extends DomainService{

    @Autowired
    private EntityManager entityManager;
    @Autowired
    private EnumerationRepository enumerationRepository;

    /***
     * 查询权责发生制
     */
    public JSONObject getAccrualBasis(SimpleRequest request) {
        JSONObject jsonObject = request.getJO();
        JSONObject company = (JSONObject)jsonObject.get("company");
        String companyId = company.get("id").toString();
        String createDateStartFormat = "";
        String createEndStartFormat = "";
        JSONArray createDate = (JSONArray)jsonObject.get("createDate");
        if(createDate != null){
            createDateStartFormat = DateUtil.format(DateUtil.parse(createDate.get(0).toString()), "yyyy-MM-dd");
            createEndStartFormat = DateUtil.format(DateUtil.parse(createDate.get(1).toString()), "yyyy-MM-dd");
        }
        String createDateStartSql = "".equals(createDateStartFormat) ? " AND 1 = 1 " : " AND TRUNC(A.CREATE_DATE) >= to_date('" + createDateStartFormat + "','yyyy-MM-dd') ";
        String createDateEndSql = "".equals(createEndStartFormat) ? " AND 1 = 1 " : " AND TRUNC(A.CREATE_DATE) <= to_date('" + createEndStartFormat + "','yyyy-MM-dd') ";
        LinkedList<Map<String, Object>> linkedList = new LinkedList<>();
        List<Enumeration> enumerationList = enumerationRepository.findByTypeAndDate("accrualBasisType");
        //为实现前端效果需要每种费用类别分开查询拼接结果
        enumerationList.forEach(enumeration -> linkedList.addAll(createNativeQuery(companyId,createDateStartSql,createDateEndSql,enumeration)));
        Map<String, Object> hashMap = new HashMap<>();
        linkedList.forEach(map -> {
            //type1为字体加粗的合计金额
            if("1".equals(map.get("TYPE"))){
                //汇总统计收入金额
                if("主营业务收入".equals(map.get("FEE_TYPE_NAME"))||"营业外收入".equals(map.get("FEE_TYPE_NAME"))){
                    Double amount = Arith.round(Double.parseDouble(map.get("AMOUNT").toString()),2);
                    Double oldAmount = 0.0;
                    if(hashMap.containsKey("income")) oldAmount = Arith.round(Double.parseDouble(hashMap.get("income").toString()),2);
                    hashMap.put("income",Arith.round(amount + oldAmount,2));
                    if("主营业务收入".equals(map.get("FEE_TYPE_NAME"))) hashMap.put("主营业务收入",Double.parseDouble(map.get("AMOUNT").toString()));
                } else {
                    //汇总统计成本金额
                    Double amount = Arith.round(Double.parseDouble(map.get("AMOUNT").toString()),2);
                    Double oldAmount = 0.0;
                    if(hashMap.containsKey("cost")) oldAmount = Arith.round(Double.parseDouble(hashMap.get("cost").toString()),2);
                    hashMap.put("cost",Arith.round(amount + oldAmount,2));
                }
            }
        });
        //计算利润金额
        hashMap.put("profit",Arith.round((Double)hashMap.get("income") - (Double)hashMap.get("cost"),2));
        linkedList.add(hashMap);
        //计算利润率
        if((Double)hashMap.get("profit") == 0.0 || (Double)hashMap.get("主营业务收入") == 0.0){
            hashMap.put("profitMargin",0);
        } else {
            hashMap.put("profitMargin",Arith.round(((Double)hashMap.get("profit") / (Double)hashMap.get("主营业务收入")) * 100,2));
        }
        hashMap.put("FEE_TYPE_NAME","利润");
        hashMap.put("TYPE","1");
        hashMap.put("AMOUNT",hashMap.get("profit"));
        JSONObject jo = new JSONObject();
        jo.put("list",linkedList);
        jo.put("resultMessage","利润"+hashMap.get("profit")+"=收入"+hashMap.get("income")+"-成本"+hashMap.get("cost")+"; 利润率: "+hashMap.get("profitMargin")+"%");
        return jo;
    }

    public LinkedList<Map<String, Object>> createNativeQuery(String companyId,String createDateStartSql,String createDateEndSql,Enumeration enumeration){
        StringBuffer sSql = new StringBuffer();
        sSql.append("SELECT SUM(A.AMOUNT) AMOUNT,A.FEE_TYPE_NAME,'2' TYPE " +
                "  FROM RCL_ACCRUAL_BASIS A " +
                " WHERE A.ACCRUAL_BASIS_TYPE = '"+enumeration.getId()+"' " +
                " AND A.COMPANY_ID = '"+ companyId +"' " + createDateStartSql + createDateEndSql +
                " GROUP BY A.FEE_TYPE_NAME" +
                " ORDER BY A.FEE_TYPE_NAME");
        Query query = entityManager.createNativeQuery(sSql.toString());
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        LinkedList<Map<String, Object>> linkedList = new LinkedList<>();
        double amount = 0;
        List<Map<String, Object>> listMap = query.getResultList();
        //汇总这个费用类别金额
        if(!listMap.isEmpty()){
            amount = listMap.stream().mapToDouble(map -> Double.parseDouble(map.get("AMOUNT").toString())).sum();
        }
        //创建一个主费用类别存储汇总金额
        Map<String, Object> maps = new HashMap<>();
        maps.put("FEE_TYPE_NAME",enumeration.getDescription());
        maps.put("AMOUNT",amount);
        maps.put("TYPE","1");
        linkedList.add(maps);
        linkedList.addAll(listMap);
        return linkedList;
    }

    public Map download(SimpleRequest request) {
        JSONObject jo = request.getJO();
        JSONObject condition = jo.getJSONObject("condition");
        Page paged = paged(Objects.requireNonNull(MapUtil.mapped(condition.get("accrualBasis"))), request.get("page"), request.get("size"), null);
        return MapUtil.mapper("content", paged.getContent(), "total", paged.getTotalElements(), "pages", paged.getTotalPages(), "page", request.get("page"));
    }
}
